package owl;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.Map;
import java.util.Set;

import org.coode.owlapi.manchesterowlsyntax.ManchesterOWLSyntaxEditorParser;
import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.expression.OWLEntityChecker;
import org.semanticweb.owlapi.expression.ParserException;
import org.semanticweb.owlapi.expression.ShortFormEntityChecker;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLDataPropertyExpression;
import org.semanticweb.owlapi.model.OWLEntity;
import org.semanticweb.owlapi.model.OWLLiteral;
import org.semanticweb.owlapi.model.OWLNamedIndividual;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyCreationException;
import org.semanticweb.owlapi.model.OWLOntologyManager;
import org.semanticweb.owlapi.reasoner.Node;
import org.semanticweb.owlapi.reasoner.NodeSet;
import org.semanticweb.owlapi.reasoner.OWLReasoner;
import org.semanticweb.owlapi.reasoner.OWLReasonerFactory;
import org.semanticweb.owlapi.util.BidirectionalShortFormProvider;
import org.semanticweb.owlapi.util.BidirectionalShortFormProviderAdapter;
import org.semanticweb.owlapi.util.ShortFormProvider;
import org.semanticweb.owlapi.util.SimpleShortFormProvider;

import uk.ac.manchester.cs.jfact.JFactFactory;

/**
 * Author: Matthew Horridge<br>
 * The University of Manchester<br>
 * Bio-Health Informatics Group<br>
 * Date: 13-May-2010 <br>
 * An example that shows how to do a Protege like DLQuery. The example contains
 * several helper classes:<br>
 * DLQueryEngine - This takes a string representing a class expression built
 * from the terms in the signature of some ontology. DLQueryPrinter - This takes
 * a string class expression and prints out the sub/super/equivalent classes and
 * the instances of the specified class expression. DLQueryParser - this parses
 * the specified class expression string
 */
public class DLQueryAgent {
	private static final IRI ONTOLOGY_IRI = IRI.create("./res/Project.owl");
	OWLOntologyManager manager = null;
	OWLOntology ontology = null;
	OWLReasoner reasoner = null;
	static DLQueryPrinter dlQueryPrinter = null;
	
	
	public DLQueryAgent(){
		try {
			// Load an example ontology. In this case, we'll just load the pizza
			// ontology.
			 manager = OWLManager.createOWLOntologyManager();
			 ontology = manager
					.loadOntologyFromOntologyDocument(new File(
							"./res/Project.owl"));
			System.out.println("Loaded ontology: " + ontology.getOntologyID());
			// We need a reasoner to do our query answering
			 reasoner = createReasoner(ontology);
			// Entities are named using IRIs. These are usually too long for use
			// in user interfaces. To solve this
			// problem, and so a query can be written using short class,
			// property, individual names we use a short form
			// provider. In this case, we'll just use a simple short form
			// provider that generates short froms from IRI
			// fragments.
			ShortFormProvider shortFormProvider = new SimpleShortFormProvider();
			// Create the DLQueryPrinter helper class. This will manage the
			// parsing of input and printing of results
			 dlQueryPrinter = new DLQueryPrinter(
					new DLQueryEngine(reasoner, shortFormProvider),
					shortFormProvider);
			// Enter the query loop. A user is expected to enter class
			// expression on the command line.
		} catch (OWLOntologyCreationException e) {
			System.out.println("Could not load ontology: " + e.getMessage());
		} 
		
	}

	@SuppressWarnings("javadoc")
	public static void main(String[] args) {
		DLQueryAgent dl= new DLQueryAgent();
		try {
			dl.doQueryLoop(dlQueryPrinter);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void doQueryLoop(DLQueryPrinter dlQueryPrinter)
			throws IOException {
		while (true) {
			// Prompt the user to enter a class expression
			System.out
					.println("Please type a class expression in Manchester Syntax and press Enter (or press x to exit):");
			System.out.println("");
			String classExpression = readInput();
			// Check for exit condition
			if (classExpression.equalsIgnoreCase("x")) {
				break;
			}
			dlQueryPrinter.askQuery(classExpression.trim());
			System.out.println();
			System.out.println();
		}
	}

	public  String  doQuery(String classExpression) {
		// Prompt the user to enter a class expression
		return dlQueryPrinter.askQuery(classExpression.trim());
	}

	private static String readInput() throws IOException {
		InputStream is = System.in;
		InputStreamReader reader;
		reader = new InputStreamReader(is, "UTF-8");
		BufferedReader br = new BufferedReader(reader);
		return br.readLine();
	}

	public static OWLReasoner createReasoner(OWLOntology rootOntology) {
		// We need to create an instance of OWLReasoner. An OWLReasoner provides
		// the basic query functionality that we need, for example the ability
		// obtain the subclasses of a class etc. To do this we use a reasoner
		// factory.
		// Create a reasoner factory.
		OWLReasonerFactory reasonerFactory = new JFactFactory();
		return reasonerFactory.createReasoner(rootOntology);
	}
}
